package com.hkts.sinoiov.utils;

import com.hkts.sinoiov.sinoiovHisTrack.entity.SinoiovHisTrack;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class Douglas {

    /**
     * 存储采样点数据链表
     */
    public static List<SinoiovHisTrack> points = new ArrayList<SinoiovHisTrack >();
    /**
     * 控制数据经度压缩的极差
     */
    private static final double D = 0.0001;

    /**
     * 对矢量曲线进行压缩
     *
     * @param from 曲线的起始点
     * @param to   曲线的终止点
     */
    public static void compress(SinoiovHisTrack from, SinoiovHisTrack to) {
        /**
         * 压缩算法的开关
         */
        boolean switchvalue = false;
        /**
         * 由起始点和终止点构成直线方程一般式的系数
         */
        double fromLat = from.getLat().doubleValue();
        double fromLng = from.getLon().doubleValue();
        double toLat = to.getLat().doubleValue();
        double toLng = to.getLon().doubleValue();
        double A = (fromLat - toLat)
                / Math.sqrt(Math.pow((fromLat - toLat), 2)+ Math.pow((fromLng - toLng), 2));


        /**
         * 由起始点和终止点构成直线方程一般式的系数
         */
        double B = (toLng - fromLng)
                / Math.sqrt(Math.pow((fromLat - toLat), 2)
                + Math.pow((fromLng - toLng), 2));
        /**
         * 由起始点和终止点构成直线方程一般式的系数
         */
        double C = (fromLng * toLat - toLng * fromLat)
                / Math.sqrt(Math.pow((fromLat - toLat), 2)
                + Math.pow((fromLng - toLng), 2));

        double d = 0;
        double dmax = 0;
        int m = points.indexOf(from);
        int n = points.indexOf(to);
        if (n == m + 1){ return;}

        SinoiovHisTrack middle = null;
        List<Double> distance = new ArrayList<>();
        for (int i = m + 1; i < n; i++) {
            double blng = points.get(i).getLon().doubleValue();
            double blat = points.get(i).getLat().doubleValue();
            d = Math.abs(A * (blng) + B * (blat) + C) / Math.sqrt(Math.pow(A, 2) + Math.pow(B, 2));
            distance.add(d);
        }
        dmax = distance.get(0);
        for (int j = 1; j < distance.size(); j++) {
            if (distance.get(j) > dmax){
                dmax = distance.get(j);
            }

        }
        if (dmax > D) {
            switchvalue = true;


        } else{
            switchvalue = false;
        }

        if (!switchvalue) {
            //删除Points(m,n)内的坐标
            for (int i = m + 1; i < n; i++) {
                points.get(i).setIsUse(SinoiovHisTrack.USE_NO);
            }
        } else {
            for (int i = m + 1; i < n; i++) {
                double blng = points.get(i).getLon().doubleValue();
                double blat = points.get(i).getLat().doubleValue();
                if ((Math.abs(A * (blng) + B
                        * (blat) + C)
                        / Math.sqrt(Math.pow(A, 2) + Math.pow(B, 2)) == dmax)){
                    middle = points.get(i);
                }

            }
            compress(from, middle);
            compress(middle, to);
        }
    }

    public static List<SinoiovHisTrack > douglasData(List<SinoiovHisTrack> source) {
        points = source;
//        System.out.println("压缩前：");
//
//        for (int i = 0; i < points.size(); i++) {
//            SinoiovHisTrack p = points.get(i);
//            System.out.print("[" + p.getLon() + "," + p.getLat() + "],");
//        }
        if(!CollectionUtils.isEmpty(points)){
            compress(points.get(0), points.get(points.size() - 1));
        }
//        System.out.println("\n压缩后：");
        List<SinoiovHisTrack > list = new ArrayList<>();
        for (int i = 0; i < points.size(); i++) {
            SinoiovHisTrack p = points.get(i);
            if (p.getIsUse()!=SinoiovHisTrack.USE_NO) {
                list.add(p);
                System.out.println("[" + p.getLon() + "," + p.getLat() + "],");
            }
        }
        return list;
    }


    public static void main(String[] args) {
        List<SinoiovHisTrack> list = new ArrayList<>();
        SinoiovHisTrack data=null;

        String[] $points = new String []{"117.212448,39.133785", "117.212669,39.133667", "117.213165,39.133297", "117.213203,39.13327", "117.213554,39.133099", "117.213669,39.13295", "117.213921,39.132462", "117.214088,39.132126", "117.214142,39.131962", "117.214188,39.13176", "117.214233,39.131397", "117.21418,39.13055", "117.214279,39.130459", "117.214539,39.130375", "117.214874,39.130188", "117.216881,39.128716", "117.217598,39.127995", "117.217972,39.12759", "117.218338,39.127178", "117.218407,39.127071", "117.218567,39.126911", "117.219704,39.125702", "117.219795,39.12561", "117.220284,39.125114", "117.220619,39.124802", "117.221046,39.124348", "117.221138,39.124245", "117.221268,39.124092", "117.222321,39.122955", "117.222824,39.122406", "117.222916,39.122311", "117.223663,39.121544", "117.2239,39.121452", "117.224113,39.12159", "117.224251,39.121677", "117.225136,39.122208", "117.225281,39.122292", "117.225319,39.122311", "117.226273,39.122875", "117.226685,39.123127", "117.227371,39.12352", "117.227806,39.123779", "117.228477,39.124134", "117.228531,39.124161", "117.228531,39.124161", "117.228668,39.124187", "117.228897,39.124325", "117.229767,39.12479", "117.230927,39.12545", "117.231186,39.12561", "117.231659,39.125908", "117.231834,39.126026", "117.232018,39.126186", "117.232185,39.126362", "117.232353,39.126583", "117.232658,39.126972", "117.232658,39.126972", "117.233124,39.12748", "117.233253,39.127609", "117.233368,39.127689", "117.233513,39.127762", "117.233665,39.127823", "117.233734,39.127846", "117.233833,39.127865", "117.233994,39.127888", "117.234138,39.127892", "117.234329,39.127884", "117.234612,39.127838", "117.234955,39.127754", "117.235252,39.12767", "117.236282,39.12738", "117.237137,39.127129", "117.237671,39.126961", "117.237953,39.126949", "117.238213,39.126865", "117.238472,39.126793", "117.2397,39.126434", "117.242233,39.125698", "117.243538,39.12532", "117.243645,39.125298",};
        System.out.println("抽稀前---------------"+$points.length);
        for(int i=0;i<$points.length;i++){

            data= new SinoiovHisTrack();
            data.setLon(new BigDecimal($points[i].split(",")[0]));
            data.setLat(new BigDecimal($points[i].split(",")[1]));
            data.setIsUse(SinoiovHisTrack.USE_YES);
            list.add(data);
        }
        List<SinoiovHisTrack> gpsDataList=  douglasData(list);
        System.out.println("---------------"+gpsDataList.size());
        System.out.println(gpsDataList.toString());

    }
}
